/*
 * Main part: select TPs at different levels
 * 
 */

package pointtest;
import java.util.ArrayList;

/**
 *
 * @author Administrator
 */
public class TPofHueristic {
    public StockPrice[] prices;
    public int priceCount,P;
    public int[] PointLevel1;
    public int[] PointLevel2;
    public int[] PointLevel3;
    public int[] PointLevel4,PIP;
    
   TPofHueristic(String stockid, String date1, String date2)
    {
       jdbcmysql db = new jdbcmysql();
       db.initial();
       prices = db.getStockPrice(stockid,date1,date2);
       priceCount = db.getPriceCount();

       // for testing example
        //  ConfigurePrice();
       PointsOn4Levels();
       PIP();

       PointLevel1 = different(PointLevel1);PointLevel2 = different(PointLevel2);PointLevel3 = different(PointLevel3);PointLevel4 = different(PointLevel4);
   }

    private void ConfigurePrice()
   {
       prices = null;
       int n = 13;
       prices = new StockPrice[n];
       prices[0]= new StockPrice("0",0);prices[1]=new StockPrice("1",2);prices[2]=new StockPrice("2",0.7);
       prices[3]= new StockPrice("0",1.5);prices[4]=new StockPrice("1",1);prices[5]=new StockPrice("2",2.6);
       prices[6]= new StockPrice("0",1.7);prices[7]=new StockPrice("1",1.9);prices[8]=new StockPrice("2",0.95);
       prices[9]=new StockPrice("2",3.1); prices[10]=new StockPrice("2",2.2); prices[11]=new StockPrice("2",2.9);
       prices[12]=new StockPrice("2",2.3);
       priceCount = n;

       PointLevel1 = new int[n];
       for(int i =0;i< n;i++)
           PointLevel1[i] = i;
   }
    private double ErrorPiP(int i, int j) // max distance
   {
       double error = 0;
       double p1= prices[i].Price,p2=prices[j].Price;
       double n=( p2-p1)/ (j-i);
        for(int k = i+1;k<=j;k++)
        {
           double Price,p3=prices[k].Price;
           double e = Math.abs(p1 + n *(k-i) - p3);
           if (e>error)
           {
               error = e;
               P=k;
            }
        }
       return error;
   }

    public void PIP()
   {
       PIP = new int [priceCount];
       ArrayList points =new ArrayList();
       points.add(0);
       points.add(priceCount-1);

       for(int i = PIP.length-1;i>0;i--)
       {
           double error = 0;
           int index =0 ;
           for(int j=0;j<points.size()-1;j++)
           {
               int t1 = Integer.parseInt (points.get(j).toString());
               int t2 = Integer.parseInt (points.get(j+1).toString());


               double p1=prices[t1].Price,p2=prices[t2].Price;

               double e = ErrorPiP(t1,t2);
               if(e>error)
               {
                   error = e;
                   PIP[i]=P;

               }
            }

       int j = 0;
       for(;Integer.parseInt (points.get(j).toString())<PIP[i];j++)
          ;
       points.add(j,PIP[i]);
     }
   }

   public int [] different(int [] PL)
   {
       int x = 0;
       for(int i = 0;i<PL.length-1;i++)
       {
           if(PL[i]!=PL[i+1])
               x++;
       }
       x++;
       int[] PLD = new int[x];
       int index = -1;
       for(int i =0;i<PL.length-1&&PL[i]<priceCount;i++)
       {
           if(i==0)
               PLD[++index] = PL[i];
           else if (PL[i]!=PLD[index]&&PL[i]>0)
               PLD[++index] = PL[i];
           else
               ;
       }
       if(index<x-1)
           PLD[++index] = PL[PL.length-1];
       return PLD;
   }

   public void PointsOn4Levels()
    {
       getTP1();

       PointLevel2= getHiggerTP(PointLevel1);

       PointLevel3= getHiggerTP(PointLevel2);

       PointLevel4= getHiggerTP(PointLevel3);

    }

   public void getTP1()
   {

       int CountTP=0;
       int[] storeIndex = new int[priceCount];
       
       storeIndex[0]= 0;
       int i =1;
       for(;i<priceCount-1;i++)
       {
           if((prices[i].Price>prices[i-1].Price && prices[i].Price>prices[i+1].Price)
              ||(prices[i].Price<prices[i-1].Price&&prices[i].Price<prices[i+1].Price))
                storeIndex[++CountTP]=i;
       }

       storeIndex[++CountTP]=prices.length-1;

       PointLevel1= new int[CountTP+1];
       for(int k=0; k<= CountTP;k++)
           PointLevel1[k]= storeIndex[k];
   }
   public int[] getHiggerTP(int[] lowlevel)
   {
       int CountTP=0;
       int[] storeIndex = new int[lowlevel.length];
       int i =0;
       for(;i<lowlevel.length-3;)
       {
           storeIndex[CountTP++]=lowlevel[i];
           if(combineTPs(lowlevel[i],lowlevel[i+1],lowlevel[i+2],lowlevel[i+3]))
               i+=3;
           else
               i++;
       }

      for(;i < lowlevel.length&&lowlevel[i]>0;i++)
          storeIndex[CountTP++]=lowlevel[i];


       int[] PointLevel= new int[CountTP];
       int TrendCount=0;
       PointLevel[TrendCount] = storeIndex[0];

       int k=1;
       for(; k< CountTP-2;k++)
       {
           if(storeIndex[k-1]<priceCount && storeIndex[k]<priceCount && storeIndex[k+1]<priceCount)
           {
           double p1=prices[storeIndex[k-1]].Price, p2=prices[storeIndex[k]].Price, p3=prices[storeIndex[k+1]].Price;
           if((p2<p1&&p2<p3)||(p2>p1 && p2>p3))
           {
               PointLevel[++TrendCount] = storeIndex[k];
           }
           }
        }
       for(;k< CountTP&&storeIndex[k]>0;k++)
        PointLevel[++TrendCount] = storeIndex[k];

       return PointLevel;
   }

   private boolean combineTPs(int t1,int t2,int t3, int t4)//,int length)
   {
       if(t4<priceCount&&t3<priceCount&&t2<priceCount&&t1<priceCount&&t1>-1)
       {
       double p1=prices[t1].Price,
               p2=prices[t2].Price,
               p3=prices[t3].Price,
               p4=prices[t4].Price;

       if(p1<p2 && p2>=p3 && p4>p2 && p4>p3 && p2-p3 < 0.7*(p2-p1))
           return true;
       else if (p1>p2 && p2<=p3 && p4<p2 && p4<p3 && p3-p2< 0.7*(p1-p2))
           return true;
       else if ((Math.abs(p1-p3)<0.2*Math.abs(p2-p1)||Math.abs(p2-p4)<0.2*Math.abs(p4-p3)))
           return true;
       else
           return false;
       }
      else
         return false;
    }

   public int[] caculateTrends(int v1,int v2,int[] lowLevel)
   {
       int trends[] = new int[2]; trends[0]=0;trends[1]=0;
       int i=0;
       for(;i<lowLevel.length-1&&lowLevel[i]!=v1;i++)
           ;
       for(; i<lowLevel.length-2&&lowLevel[i]!=v2;i++)
       {
           if(prices[lowLevel[i]].Price<prices[lowLevel[i+1]].Price)
               trends[0]++;
           else
               trends[1]++;
       }
       return trends;
   }
}
